package gui.GLListeners;

import figuras.BSplines;
import figuras.PuntoVector;
import figuras.Recta;
import figuras.malla.MallaHoja;
import handlers.BSplinesHandler;
import handlers.RLHandler;

import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.glu.GLU;

import utils.SistemaCoordenadas;
import utils.UnidadesGraficas;
import camaras.Camara;

import componentes.flor.Hoja;

import constantes.Consts;
import dataType.ContornoHoja;
import event.changeHoja.ChangeHoja;

public class GLListenerCreacionHoja extends GLListenerCurvas {
	
	private RLHandler manejadorRL;
	private ContornoHoja contornoHoja;
	private ChangeHoja changeHojaManager;
	private Hoja hoja;

	public GLListenerCreacionHoja() {		
		glu = new GLU();
		xRight = Consts.XRIGHT_GLL_CREAR_HOJA;
		xLeft = -xRight;
		yTop = Consts.YTOP_GLL_CREAR_HOJA;
		yBot = -xRight;
		xCentro = (xRight + xLeft) / 2.0; // =0;
		yCentro = (yTop + yBot) / 2.0; // =0;
		RatioViewPort = 1.0;
		manejadorSplines=new BSplinesHandler();
		manejadorRL = new RLHandler();		
		contornoHoja = null;
		hoja = null;
	}


	public void init(GLAutoDrawable glDrawable) {
		gl = glDrawable.getGL();
		gl.glClearColor(0.6f, 0.7f, 0.8f, 1.0f);
		//gl.glClearColor(0.f, 0.1f, 0.1f, 1.0f);
		
		// Radio del Volumen de Vista =1
		RatioViewPort = 1.0;
		PuntoVector eye = new PuntoVector(0, 0, 300, 1);
		PuntoVector look = new PuntoVector(0, 0, 0, 1);
		PuntoVector up = new PuntoVector(0, 1, 0, 0);
		int flag = 0;// 0 Ortogonal 1 perspectiva
		// if (camara == null)
		camara = new Camara(eye, look, up, flag, xLeft, xRight, yBot, yTop, 1,
				1000, 90, 0.5, gl, glu);
	}


	public void display(GLAutoDrawable glDrawable) {
		gl = glDrawable.getGL();

		gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

		UnidadesGraficas.cruzetaDoble(xRight, gl);

		gl.glPointSize(3.0f);
		gl.glLineWidth(3.0f);
		gl.glBegin(GL.GL_LINE_STRIP);
		for (int i = 0; i < manejadorSplines.getPuntosIntroducidos().size(); i++) {
			gl.glVertex3d(manejadorSplines.getPuntosIntroducidos().get(i)
					.getX(), manejadorSplines.getPuntosIntroducidos().get(i)
					.getY(), manejadorSplines.getPuntosIntroducidos().get(i)
					.getZ());

		}
		gl.glEnd();
		gl.glLineWidth(1.0f);

		for (BSplines b : manejadorSplines.getBsplines()) {
			b.pintaConLineas(gl);
			b.pintaConPuntos(gl);
		}

		gl.glFlush();			
	}

	public void mousePressed(MouseEvent me,double width, double height) {
		this.setChanged();
		this.notifyObservers();
		
		double x = (me.getX())* ((this.xRight - this.xLeft) / width)
					+ this.xLeft - this.xCentro;
		double y = (-me.getY())* ((this.yTop - this.yBot) / height)
			+ this.yTop - this.yCentro;
			


		if ((manejadorSplines.getPMouse() == null) && (manejadorSplines.getPuntoModificado() == -1) && (!manejadorSplines.isPinta())) {
			manejadorSplines.setPMouse(new PuntoVector((float) x, (float) y, 0.0f, 1));
			if (manejadorSplines.getBsplines().size() != 0) {
				ArrayList<PuntoVector> puntos = manejadorSplines.getBsplines().get(
						manejadorSplines.getBsplines().size() - 1).getPuntosControl();
				for (int i = 0; i < puntos.size(); i++) {
					double dist = manejadorSplines.getPMouse().distancia(puntos.get(i));
					if (dist < xRight/40) {
						manejadorSplines.setPMouse(puntos.get(i));
						manejadorSplines.setPuntoModificado(i);
					}
				}
				if (manejadorSplines.getPuntoModificado() == -1) {
					manejadorSplines.setPinta(true);
					// pMouse=null;
				}
			}
		}
	}

	public void mouseReleased(MouseEvent me) {
		this.setChanged();
		this.notifyObservers();
		try {
			if (manejadorSplines.getPuntoModificado() != -1) {
				manejadorSplines.getBsplines().get(
						manejadorSplines.getBsplines().size() - 1)
						.getPuntosControl().remove(
								manejadorSplines.getPuntoModificado());
				manejadorSplines.getBsplines().get(
						manejadorSplines.getBsplines().size() - 1)
						.getPuntosControl().add(
								manejadorSplines.getPuntoModificado(),
								new PuntoVector(manejadorSplines.getPMouse()));
			} else {
				manejadorSplines.setPinta(false);
				if (manejadorSplines.getBsplines().size() < manejadorSplines
						.getMaxSplines()) {
					this.sacaPuntosControl();
					this.manejadorSplines.addSpline();
				}
			}
			manejadorSplines.setPuntoModificado(-1);
			manejadorSplines.setPMouse(null);

			if (manejadorSplines.getBsplines().size() == manejadorSplines
					.getMaxSplines()) {
				for (BSplines b : manejadorSplines.getBsplines())
					b.perfilaSpline();
				
				contornoHoja = manejadorSplines.getContornoHoja();
				contornoHoja = manejadorRL.generaContorno(contornoHoja);
				SistemaCoordenadas.trasladaContornoHoja(contornoHoja, (float)yTop,
						(float) (2*yTop)-10);
				if (manejadorRL.isHayInterseccion() && contornoHoja != null) {

					manejadorRL.dibuja(gl);

					gl.glPointSize(6.0f);
					Recta recta = new Recta(contornoHoja.getLinea(0).get(0),
							contornoHoja.getLinea(0).get(
									contornoHoja.getLinea(0).size() - 1));
					MallaHoja malla = new MallaHoja(contornoHoja, recta,
							Consts.MALLA_HOJA_DIVX, Consts.MALLA_HOJA_DIVY);

					hoja = new Hoja(malla, gl);
					changeHojaManager.launchEvent(hoja);

				}
			}
		} catch (Exception e) {
			manejadorRL = new RLHandler();
			manejadorSplines = new BSplinesHandler();
			contornoHoja = null;
			hoja = null;
		}
		
	}

	public void mouseDragged(MouseEvent me,double width, double height) {
		this.setChanged();
		this.notifyObservers();
		double x = (me.getX())
				* ((this.xRight - this.xLeft) / width)
				+ this.xLeft - this.xCentro;
		double y = (-me.getY())
				* ((this.yTop - this.yBot) / height)
				+ this.yTop - this.yCentro;
		
		if (!manejadorSplines.isPinta()) {
			if (/* (pMouse != null) && */(manejadorSplines.getPuntoModificado() != -1)) {
				manejadorSplines.getPMouse().setX((float) x);
				manejadorSplines.getPMouse().setY((float) y);
			}
		} else {
			if(manejadorSplines.getBsplines().size()<manejadorSplines.getMaxSplines()){
			PuntoVector pDragged = new PuntoVector((float) x, (float) y, 0.0f,
					1);
			manejadorSplines.getPuntosIntroducidos().add(pDragged);
			}
		}
	}

	

	public void limpiaCurvas() {
		manejadorSplines.limpiaCurvas();
		BSplines b = new BSplines();
		manejadorSplines.getBsplines().add(b);
	}

	public void addChangeHoja(ChangeHoja changeHojaManager){
		this.changeHojaManager = changeHojaManager;
	}
	
	public void keyPressed(KeyEvent ke) {
		
	}
}
